{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 总任务\n",
    "针对“发票样例”中的以压缩文件形式存放的发票文件\n",
    "1 通过python 解压成单独的pdf文件格式的电子发票文件\n",
    "2 读取pdf文件中的信息，在mysql数据库中建立相应的数据表，将读取的信息存入数据表中\n",
    "3 建立web服务器，连接第2步得到的mysql数据库，为用户提供发票的查询服务与下载服务，将满足查询条件的多张发票打包下载\n",
    "4 批量打印满足查询条件的多张发票\n",
    "\n",
    "### （1）解压zip文件\n",
    "通过python 解压成单独的pdf文件格式的电子发票文件。\n",
    "通过手动解压缩发现该压缩文件里面还有压缩文件，所以需要递归的进行解压缩。\n",
    "\n",
    "由于我们系统中只有zip格式的压缩文件，所以下面的代码只能用于解压zip格式的压缩文件，但是其他压缩类型的文件可以以此类推。\n",
    "\n",
    "在这里面需要学会几个函数的使用：\n",
    "- zipfile.ZipFile()：传入文件路径，获取压缩文件内的信息\n",
    "- zipfile.namelist()：获取该目录下的文件夹名和文件名\n",
    "- zipfile.extract()：解压文件到指定目录，包括文件夹\n",
    "- str.endswith()：匹配文件后缀\n",
    "- list_dir()：列出指定路径下的文件夹名和文件名\n",
    "\n",
    "以下代码为递归解压缩的代码："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [],
   "source": [
    "import shutil\n",
    "import zipfile\n",
    "import os"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "解压文件名称： invoice/\n",
      "解压文件名称： invoice/91510100633168022E_937083446ff948eba0b1f6a46a88ed52.pdf\n",
      "解压文件名称： invoiceDetail/\n",
      "解压文件名称： invoiceDetail/apply.pdf\n",
      "解压文件名称： invoiceDetail/trans.pdf\n",
      "解压文件名称： invoice.zip\n",
      "解压文件名称： 91510000709155317M_44308ed89a5c467e9ede236eb1efd8bc.pdf\n",
      "解压文件名称： 91510000689940624C_97ca15ecff3a4e9b853c62001dc0db55.pdf\n",
      "解压文件名称： invoiceDetail.zip\n",
      "解压文件名称： apply.pdf\n",
      "解压文件名称： trans.pdf\n",
      "解压文件名称： invoice.zip\n",
      "解压文件名称： 91510100633168022E_140d21c2dcd3468eaf56816d9190eb5e.pdf\n",
      "解压文件名称： 91510000709155317M_05fc60ecab6343deb5d96fb6b94e61f4.pdf\n",
      "解压文件名称： 91510000689919120D_f3c17dea5202450daa1d6b293390644c.pdf\n",
      "解压文件名称： invoiceDetail.zip\n",
      "解压文件名称： apply.pdf\n",
      "解压文件名称： trans.pdf\n"
     ]
    }
   ],
   "source": [
    "# 简洁版，仅用于递归的方式解压文件\n",
    "def recursive_unzip(path, zfile):\n",
    "    \"\"\"解压缩文件\"\"\"\n",
    "    # file_path用于解压缩文件；des_dir用于存放下一级的解压缩的同名目录\n",
    "    file_path = os.path.join(path, zfile)\n",
    "    des_dir = os.path.join(path, zfile[:-4])\n",
    "    srcfile = zipfile.ZipFile(file_path) # 获取解压文件信息\n",
    "    for file_name in srcfile.namelist(): # 获取解压文件下的目录\n",
    "        srcfile.extract(file_name, des_dir) # 将zip文档内的指定文件解压到当前目录\n",
    "        print(\"解压文件名称：\",file_name)\n",
    "        if file_name.endswith('.zip'): # 如果是压缩文件，则进入下一级解压\n",
    "            path = des_dir\n",
    "            zfile = file_name\n",
    "            recursive_unzip(path, zfile)\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    # 文件路径 及 该路径下的压缩文件\n",
    "    path = r'../发票样例/' \n",
    "    zfiles =  [file for file in os.listdir(path) if file[-3:] == 'zip']\n",
    "    for file in zfiles:\n",
    "        recursive_unzip(path, file)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 复杂版，解压文件后自动删除源文件\n",
    "recursive_unzip_file = []\n",
    "\n",
    "def recursive_unzip(path, zfile):\n",
    "    # file_path用于解压缩文件；des_dir用于存放下一级的解压缩的同名目录\n",
    "    file_path = os.path.join(path, zfile)\n",
    "    des_dir = path + zfile[:zfile.index('.zip')]\n",
    "    srcfile = zipfile.ZipFile(file_path)\n",
    "    for file_name in srcfile.namelist():\n",
    "        # 如果里面的文件是压缩文件，就递归的进入下一层目录\n",
    "        if file_name.endswith('.zip'):\n",
    "            temp_del_file = os.path.join(des_dir, file_name)\n",
    "            if temp_del_file not in recursive_unzip_file:\n",
    "                recursive_unzip_file.append(temp_del_file)\n",
    "        srcfile.extract(file_name, des_dir) # 将zip文档内的指定文件解压到当前目录\n",
    "        print(\"解压文件名称：\",file_name)\n",
    "        if file_name.endswith('.zip'):\n",
    "            temp_del_file = os.path.join(des_dir, zfile)\n",
    "            if temp_del_file not in recursive_unzip_file:\n",
    "                recursive_unzip_file.append(temp_del_file)\n",
    "\n",
    "            path = des_dir\n",
    "            zfile = file_name\n",
    "            recursive_unzip(path, zfile)\n",
    "\n",
    "def del_file(file_path):\n",
    "    \"\"\"\n",
    "    删除指定路径下的所有文件和文件夹\n",
    "    :param file_path: 路径\n",
    "    :return:\n",
    "    \"\"\"\n",
    "\n",
    "    for del_file_path in file_path:\n",
    "        if os.path.isfile(del_file_path):\n",
    "            os.remove(del_file_path)\n",
    "        elif os.path.isdir(del_file_path):\n",
    "            shutil.rmtree(del_file_path)\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    # 文件路径 及 该路径下的压缩文件\n",
    "    path = r'../发票样例/' \n",
    "    zfiles =  [file for file in os.listdir(path) if file[-3:] == 'zip']\n",
    "\n",
    "    recursive_unzip_file = [path+file for file in zfiles]\n",
    "    print(recursive_unzip_file)\n",
    "    for file in zfiles:\n",
    "        recursive_unzip(path, file)\n",
    "    del_file(recursive_unzip_file)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3.7.0 ('base')",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.0"
  },
  "orig_nbformat": 4,
  "vscode": {
   "interpreter": {
    "hash": "d2ac46498bf9d36d8c53ef3ef5f1114d28cdeda33c2544899d6ce51d38e12b9d"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
